/*
 * Scheduler.cpp
 *
 *  Created on: Dec 12, 2011
 *      Author: quotrader
 */

#include "Scheduler.h"
#include "../Task/Task.h"
#include <iostream>
#include <pthread.h>
#include <sstream>

Scheduler::Scheduler() {
	this->scheduleId = SCHED_RR;
	//this->maxPriority = sched_get_priority_max(this->scheduleId);
	this->maxPriority = 60;
	this->minPriority = sched_get_priority_min(this->scheduleId);
	this->startPriority = this->minPriority + 10;
	this->priorityIncr = 5;
}

void Scheduler::execute() {

	Task *tasks = this->tMng->tasks;
	int numTask = this->tMng->numTask;
	stringstream tmp;
	string str;
	pthread_attr_t attr;
	sched_param param;


	// send tasks to algorithm in order to sort and play with them
	this->algr->run(tMng);

	//start the scale
	this->scale->start();

	sem_init(&this->semId,0,0);

	// create the controller thread (proxy)
	pthread_create(&this->ctrThread, NULL, &Scheduler::control, this);
	pthread_setname_np(this->ctrThread, "CTR_T");


	//create and name the threads
	for (int i = 0; i < numTask; i++){
		tmp << "THREAD#" << tasks[i].id;
		str = tmp.str();
		pthread_create(&tasks[i].taskThread, NULL, &Task::run, &tasks[i]);
		pthread_setname_np(tasks[i].taskThread, str.c_str());
		tmp.str("");
	}

	//Setting thread priorities
	for (int i = 0; i < numTask; i++) {
		tasks[i].priority=this->startPriority + ((numTask-i)* this->priorityIncr);
		pthread_setschedprio(tasks[i].taskThread,tasks[i].priority);
	}
	sem_post(&this->semId);
}

void Scheduler::setup(Scale *scl, TaskMng *tm) {
	// assign scale & task manager to their handlers
	this->scale = scl;
	this->tMng = tm;
}

int Scheduler::setupPuls() {

	timer_t timerid; // timer ID for timer
	struct sigevent event; // event to deliver
	struct itimerspec timer; // the timer data structure
	int coid; // connection back to ourselves
	int chid;

	chid = ChannelCreate(0);
	if(chid==-1)cout<<"problem creating a channel";


	// create a connection back to ourselves
	coid = ConnectAttach(0, 0, chid, 0, 0);
	if(coid ==-1) cout << "problem attaching to channel";


	// set up the kind of event that we want to deliver -- a pulse
	SIGEV_PULSE_INIT (&event, coid,
			SIGEV_PULSE_PRIO_INHERIT, 2, 0);

	// create the timer, binding it to the event
	if(timer_create(CLOCK_REALTIME, &event, &timerid)==-1)cout<<"problem creating a timer";

	// setup the timer (1s delay, 1s reload)
	timer.it_value.tv_sec = 0;
	timer.it_value.tv_nsec = 1;
	timer.it_interval.tv_sec = 0;
	timer.it_interval.tv_nsec = 5000000;

	// and start it!
	if(timer_settime(timerid, 0, &timer, NULL)==-1)cout <<"problem setting a timer";

	// return channel id
	return chid;
}
